package net.jumpengine.util;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * 通用工具类
 * <br /><br />
 * <b>作者:</b>张天文 <br />
 * <b>日期:</b>2018年10月23日 下午4:45:35<br />
 * @date
 */
public class UComm {
	private static final long startTime=System.currentTimeMillis();
	private static long useTime=-1;
	
	/**
	 * 获取时间id
	 * @return id,字符串,8位,在服务器时间不倒退时不重复
	 */
	public static synchronized String timeId(){
		long now=System.currentTimeMillis();
		if(useTime==-1 || (now-useTime)>10000){
			useTime=now;
		}else{
			useTime++;
		}
		return Long.toString(useTime-startTime, 32);
	}
	
	/**
	 * 检测字符串是不是为空或长度为0
	 * @param str 字符串
	 * @return true 为空或长度为0
	 */
	public static boolean isNull(String str){
		return str==null || str.length()==0;
	}
	
	/**
	 * 判断strs中是否有空字符串
	 * @param strs 字符串数组
	 * @return -1 没有,&gt;=0,空字符串位置
	 */
	public static int isNull(String... strs){
		if(strs==null || strs.length==0)return -2;
		for(int i=0;i<strs.length;i++){
			if(strs[i]==null || strs[i].length()==0)return i;
		}
		return -1;
	}
	
	/**
	 * 检测List是不是为空或者长度为0 
	 * @param list 集合
	 * @return true 为空或长度为0
	 */
	public static boolean isNull(List<?> list){
		return list==null || list.size()==0;
	}
	
	/**
	 * 获取集合长度,null则为0
	 * @param list 集合
	 * @return 长度
	 */
	public static int size(List<?> list){
		return list==null?0:list.size();
	}
	
	/**
	 * 检测两个字符串是否内容相同,不用担心空指针
	 * @param str1 字符串1
	 * @param str2 字符串2
	 * @return true-两个字符串内容相同(同为null也是相同)
	 */
	public static boolean equals(String str1,String str2){
		if(str1==null && str2==null)return true;
		return str1==null?str2.equals(str1):str1.equals(str2);
	}
	
	/**
	 * 将数组拼接为一个字符串,空对象将跳过,对象为数组时以[a1,a2,a3..]形式拼接
	 * @param objs 对象数组
	 * @return 对象数组拼接的字符串
	 */
	public static String arrToStr(Object... objs){
		StringBuilder sbr=new StringBuilder();
		for(Object obj:objs){
			if(obj==null)continue;
			if(obj.getClass().isArray()){
				int length = Array.getLength(obj);
				for(int i=0;i<length;i++){
					if(i==0)sbr.append('[');
					sbr.append(Array.get(obj, i));
					if(i!=length-1)sbr.append(',');
					if(i==length-1)sbr.append(']');
				}
			}else if(obj instanceof Class) {
				sbr.append(((Class<?>) obj).getName());
			}else{
				sbr.append(obj);
			}
		}
		return sbr.toString();
	}
	
	/**
	 * 将数组输出到控制台,为[x1,x2,x3]形式,不是数组的直接输出.<br>
	 * 主要是因为[info/arrToStr]的可变参数不支持只有一个参数,并且是数组
	 * @param obj 对象
	 */
	public static void array(Object obj) {
		if(obj==null) {
			System.out.println("null");
			return;
		}
		if(obj.getClass().isArray() || obj instanceof List) {
			boolean isArray=obj.getClass().isArray();
			List<?> list=null;
			if(!isArray)list=(List<?>) obj;
			StringBuilder sbr=new StringBuilder();
			int length = isArray?Array.getLength(obj):list.size();
			for(int i=0;i<length;i++){
				if(i==0)sbr.append('[');
				if(isArray) {
					sbr.append(Array.get(obj, i));
				}else {
					sbr.append(list.get(i));
				}
				if(i!=length-1)sbr.append('|');
				if(i==length-1)sbr.append(']');
			}
			System.out.println(sbr);
		}else {
			System.out.println(obj);
		}
	}
	
	/**
	 * 打印map键值对
	 * @param c 当前类的class
	 * @param map map集合
	 * @param info 额外信息
	 */
	public static void showMap(Class<?> c,Map<?,?> map,Object...info){
		StringBuilder sbr=new StringBuilder("<-↓-↓-↓-↓-↓-↓->"+c.getName());
		if(info!=null){
			boolean isFirst=true;
			sbr.append(':');
			for(Object obj:info){
				if(isFirst){
					if(obj!=null)sbr.append(obj.toString());
					isFirst=false;
				}else{
					if(obj!=null)sbr.append(","+obj.toString());
				}
			}
		}
		sbr.append('\n');
		for(Object key:map.keySet()){
			sbr.append(key+":"+map.get(key)+'\n');
		}
		sbr.append("<-↑-↑-↑-↑-↑-↑-↑->");
		System.out.println(sbr.toString());
	}
	
	/**
	 * 简单的用逗号分割,不用正则,提高速度
	 * @param str 要分割的字符串
	 * @return 字符串数组
	 */
	public static String[] split(String str) {
		return split(str,',');
	}
	
	/**
	 * 简单分割,不用正则,提高速度
	 * @param str 要分割的字符串
	 * @param c 分割的字符
	 * @return 字符串数组
	 */
	public static String[] split(String str,char c) {
		if(isNull(str))return null;
		int num=0;
		for(int i=0;i<str.length();i++) {
			if(str.charAt(i)==c)num++;
			if(i==str.length()-1 && str.charAt(i)!=c)num++;
		}
		String[] strs=new String[num];
		num=0;
		StringBuilder sbr=new StringBuilder();
		for(char a:str.toCharArray()) {
			if(a!=c) {
				sbr.append(a);
			}else {
				strs[num]=sbr.toString();
				sbr.delete(0, sbr.length());
				num++;
			}
		}
		if(num==strs.length-1)strs[strs.length-1]=sbr.toString();
		return strs;
	}
	
	/**
	 * 将数组转化为List,并不是api中固定长度的
	 * @param array 数组
	 * @return ArrayList 数组为空返回null
	 */
	public static <T> List<T> arrToList(T[] array){
		if(array==null || array.length==0)return null;
		List<T> list=new ArrayList<>(array.length);
		for(T t:array) {
			list.add(t);
		}
		return list;
	}
	
	/**
	 * 产生随机数,包括min和max
	 * @param min 最小值
	 * @param max 最大值
	 * @return min与max之间的数,包含min与max
	 */
	public static int rnd(int min,int max){
		return (int) (Math.floor(Math.random()*(max-min+1))+min);
	}
	
	/**
	 * 检测字符串是否在数组中
	 * @param str 字符串
	 * @param arrs 字符串数组
	 * @return true-在数组中
	 */
	public static boolean isInArray(String str,String...arrs){
		if(arrs==null || arrs.length==0)return false;
		for(String arr:arrs){
			if(equals(arr,str))return true;
		}
		return false;
	}
	
	/**
	 * 检测str是否包含strs中的字符串
	 * @param str 字符串
	 * @param arrs 字符串数组
	 * @return true-str包含
	 */
	public static boolean isLikeArray(String str,String...arrs){
		if(arrs==null || arrs.length==0)return false;
		for(String arr:arrs){
			if(str.indexOf(arr)>=0)return true;
		}
		return false;
	}
	
	/** UUID */
	public static String uid(){
		String uid=UUID.randomUUID().toString();
		return uid.replaceAll("-", "");
	}
	
	/**
	 * 获取文件名的扩展名
	 * @param fileName 文件名
	 * @return 扩展名
	 */
	public static String extName(String fileName){
		if(isNull(fileName))return "";
		int ind=fileName.lastIndexOf('.');
		if(ind<0){
			return "";
		}else{
			return fileName.substring(ind+1);
		}
	}
	
	/**
	 * md5加密
	 * @param plainText 要加密的字符串
	 * @return md5加密后的字符串
	 */
	public static String md5(String plainText,String charset) {
		byte[] bytes = null;
		try {
			bytes=plainText.getBytes(charset);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		if(bytes!=null && bytes.length>0){
			return md5(bytes);
		}
		return null;
	}
	
	/**
	 * md5加密
	 * @param bytes 要加密的字节数组
	 * @return md5加密后的字符串
	 */
	public static String md5(byte[] bytes) {
		byte b[] = null;
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			md.update(bytes);
			b = md.digest();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		if (b != null) {
			int i;

			StringBuffer buf = new StringBuffer("");
			for (int offset = 0; offset < b.length; offset++) {
				i = b[offset];
				if (i < 0)i += 256;
				if (i < 16)buf.append("0");
				buf.append(Integer.toHexString(i));
			}
			return buf.toString();
		} else {
			return null;
		}
	}
	
	/**
	 * 产生日期格式化数据
	 * @return
	 */
	public static String nowString() {
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd kk:mm:ss");
		return sdf.format(new Date());
	}
}
